package com.kt.common.func

import com.sun.corba.se.impl.orbutil.graph.Graph
import java.util.*
import kotlin.collections.HashSet


//函数申明
fun doubleA(x: Int): Int {
    return 2 * x
}

//多个参数
fun powerOf(
    number: Int,
    exponent: Int, // trailing comma
) { /*...*/
}

//覆盖方法演示
open class A {
    open fun foo(i: Int = 10) {}
}

class B : A() {
    override fun foo(i: Int) {

    }
}

//具名参数
fun foo(
    bar: Int,
    bzz: Int,
) {
} //调用foo(bar=1,bzz=2)

//最后一个参数是lambda表达式
fun foo1(
    baz: Int,
    qux: () -> Unit,//此处Unit表示没有返回值
) {
    println(baz)
    //调用函数
    qux()
}

//申明为Unit为返回值的时候 ->fun printHello(name: String?) { …… }
fun printHello(name: String?): Unit {
    println(name)//不需要返回
}

//中缀表示法
infix fun Int.shf(i: Int): Int {
    return this + i
}

//局部函数
fun dfs() {
    val visited = HashSet<Int>()

    //局部函数 ，并且内部函数访问外部函数的变量(闭包)
    fun dfs(current: Int) {
        println(visited)
    }
}

class Sample {
    //成员函数
    fun foo() {
        print("Foo")
    }
}

//泛型函数
fun <T> singletonList(item: T): List<T> { /*……*/
    return emptyList()
}

fun getA(qux: (A: Int, B: Int) -> Int) {
    println(qux(2, 4))
}

//使用函数的方法
//1.lambda表达式
val fa = { a: Int, b: Int -> a + b }

//2.匿名函数
val fb = fun(a: Int, b: Int): Int {
    return a * b
}

//3,已有申明的可调用引用
//顶层、局部、成员、扩展函数
val fc = Int::or

//顶层、成员、扩展属性
val fd = List<Int>::size
//构造函数
//val fe = ::Regex

//应用：
//1.使用实现函数类型接口的自定义类的实例  -> 等同与java的实现一个接口 ，
// 只是此处支持lambda表达式，里边也规定了一个指定的名称invoke
class IntTransformer : (String) -> Int {
    override fun invoke(p1: String): Int {
        return p1.toInt()
    }
}
//lambda 表达式与匿名函数是“函数字面值”，即未声明的函数

//lambda表达式的完整表达方式
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }

//在函数的末尾是函数，默认放在括号之外
//此处末尾是定义一个lambda表达式
fun funLambdaTest(a: Int, b: () -> Unit) {
    b()
}

//当我们需要明确表达式的返回值类型的时候，使用匿名函数
//匿名函数后边可以有两种形式1.函数表达式 2.代码块
//fun(x: Int, y: Int): Int = x + y
/*fun(x: Int, y: Int): Int {
    return x + y
}*/
fun main() {
    //最后一个参数是lambda表达式的时候
    //foo1(1) { print("this callback") }
    /*val shf = 1.shf(2)
    println(shf)*/
    //println(5 shf 2)
    /*getA() { a, b ->
        println("a+b= ${a + b}")
        return@getA a + b
    }*/
    /*println(fa(5, 2))
    println(fb(5, 2))*/
    //println(fc(9,2))
    //println(fd(listOf(1, 2)))
    /* val intTransformer: (String) -> Int = IntTransformer()
     //intTransformer("ssd")// For input string: "ssd"
     intTransformer("213")*/

    //以下两个函数表达式相等
    /*val repeatFun0: (String, Int) -> String = { a: String, b: Int ->
        a.repeat(b)
    }
    //与上边表达式相比此处只是将String类型参数提取出来，用this来代替
    val repeatFun: String.(Int) -> String = { times ->
        this.repeat(times)
    }
    val repeatFun1: (String, Int) -> String = repeatFun
    fun runTransformation(f: String.(Int) -> String): String {
        return f.invoke("hello", 3)//等价于f("hello", 3)
    }
    val result = runTransformation(repeatFun0) // OK
    println(result)*/
    /*val stringPlus: String.(Any?) -> String = String::plus
    println(stringPlus.invoke("<---", "--->"))
    println(stringPlus("hello", "world"))*/

    //使用末尾是lambda表达式 ,这里注意如果是用匿名表达式不可
    //此处由于没有参数故使用以下方式
    /*funLambdaTest(1,b = {
        println("这是lambda表达式内部的代码，第一种方式执行")
    })
    funLambdaTest(2){
        println("这是lambda表达式内部的代码，第二种方式执行")
    }*/

    //单个参数的隐式名称 ,只有一个参数此处隐藏参数使用时用it表示
    /*val items = listOf(1,2,3,4,5)
    items.forEach {
        it
    }*/

    //从lambda表达式中返回一个值 ,lambda表达式中返回一个3
    /*val items = listOf(7, 2, 4, 5, 6)
    items.filter {
        print(it)
        //it > 3//lambda表达是在没有 return 的时候
        return@filter it > 3//这两种方式等价
    }
    items.println()*/
    /*val map = mutableMapOf<String,Int>()
    map["1"] = 2
    map["4"] = 5
    //不使用的字段使用_表示
    map.forEach{ (_, va) ->
        println(va)
    }*/

    //解构
    /*val person = Person("zs", 28)
    val (name,age) = person
    //解构表达式也可以这样写 componentN()
    var na = person.component3()
    println("我叫$name,今年${age}岁,性别$na")*/

    //表达式
    /*data class Result(val result: Int, val status: Int)
    fun function(): Result {
        return Result(12, 1)
    }

    // 现在，使用该函数：
    val (result, status) = function()
    println("result=$result,status=$status")*/
    //for循环解构
    /*for ((key, value) in map) {
        // 使用该 key、value 做些事情
    }*/
    //此处filter函数里边也可以填入一个lambda表达式或者一个匿名函数
    //在 lambda 表达式内部禁止使用裸 return
    /*val ints = listOf(1, 2, 3, 4)
    val ints1 = ints.filter(fun(item) = item > 0)
    ints1.println()
    val ints2 = ints.filter {
        it > 2
    }
    ints2.println()*/


    /*val sum: Int.(Int) -> Int = { other -> plus(other) }
    val sum1: Int.(Int) -> Int = Int::plus
    //在这样的函数字面值内部，传给调用的接收者对象成为隐式的this 就可以指代Int.(Int) 中的第一个参数
    val sum2 = fun Int.(other: Int): Int = this + other
    println(1.sum(2))
    println(sum(1, 2))
    println(sum1(3, 2))
    println(sum2(3, 2))*/

    class HTML {
        fun body() {
            println("创建body")
        }
    }

    fun html(init: HTML.() -> Unit): HTML {
        /*val html = HTML()  // 创建接收者对象
        html.init()        // 将该接收者对象传给该 lambda
        return html*/
        //与上边等效
        val html = HTML()
        init(html)
        return html
    }

    val html1 = html {       // 带接收者的 lambda 由此开始
        body()   // 调用该接收者对象的一个方法
    }

}

fun <T> List<T>.println() {
    println("size="+this.size)
    this.forEach {
        println(it)
    }
}

data class Person(val name: String, val age: Int, val sex: String = "男") {

}
